/*
 * Copyright 2012-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;

/**
 *
 * 启动Spring 应用程序上下文时进行自动配置，它会尝试猜测并配置项目可能需要的Bean。自动配置通常是基于
 * 项目classpath中引入的类和已定义的Bean来实现的。在此过程中，被自动配置的组件来自项目自身和项目依赖的jar包中
 *
 *
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @see ConditionalOnBean
 * @see ConditionalOnMissingBean
 * @see ConditionalOnClass
 * @see AutoConfigureAfter
 * @see SpringBootApplication
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
/**
 * @Import只能用在类上 ，@Import通过快速导入的方式实现把实例加入spring的IOC容器中
 * @Import的三种用法主要包括:
 * 1、直接填class数组方式
 * 2、ImportSelector方式【重点】
 * 3、ImportBeanDefinitionRegistrar方式
 *
 * 第一种用法：直接填class数组，对应的import的bean都将加入到spring容器中，这些在容器中bean名称是该类的全类名 ，比如com.yc.类名
 * 第二种用法：ImportSelector方式【重点】：这种方式的前提就是一个类要实现ImportSelector接口
 * 分析实现接口的selectImports方法中的：
 * 1、返回值： 就是我们实际上要导入到容器中的组件全类名【重点 】
 * 2、参数： AnnotationMetadata内包含了被@Import注解的类的所有注解信息
 * 第三种用法：ImportBeanDefinitionRegistrar方式
 * 同样是一个接口，类似于第二种ImportSelector用法，相似度80%，只不过这种用法比较自定义化注册，具体如下：
 * 第一步：创建Myclass2类并实现ImportBeanDefinitionRegistrar接口
 * 参数分析：
 * 第一个参数：annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
 * 第二个参数表示用于注册定义一个bean（
 * 		   RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);
 *         //注册一个bean指定bean名字（id）
 *         beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);
 *）
 * @Import注解的三种使用方式总结
 * 第一种用法：@Import（{ 要导入的容器中的组件 } ）：容器会自动注册这个组件，id默认是全类名
 * 第二种用法：ImportSelector：返回需要导入的组件的全类名数组，springboot底层用的特别多【重点 】
 * 第三种用法：ImportBeanDefinitionRegistrar：手动注册bean到容器
 *
 * */
@Import(AutoConfigurationImportSelector.class) //import注解主要提供导入配置类的功能，和xml配置中<import/>作用一样，@import导入@Configuration注解类
public @interface EnableAutoConfiguration {

	//用来覆盖开启/关闭自动配置的功能
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}
